(require 'srfi-1)
(define cria-saida
  (lambda (nome
      descricao
      sala-saida
      sala-entrada
      has-porta?
      trancada?
      chave-que-abre )
    (let ((self-nome nome)
          (self-descricao descricao)
          (self-sala-saida sala-saida)
          (self-sala-entrada sala-entrada)
          (self-has-porta? has-porta?)
          (self-trancada? trancada?)
          (self-chave-que-abre chave-que-abre))

      (lambda (selector)

        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        (cond ((eq? selector 'get-nome)
               (lambda ()
                 self-nome))

              ((eq? selector 'set-nome)
               (lambda (novo-nome)
                 (set! self-nome novo-nome)))
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

              ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
              ((eq? selector 'get-descricao)
               (lambda ()
                 self-descricao))

              ((eq? selector 'set-descricao)
               (lambda (nova-descricao)
                 (set! self-descricao nova-descricao)))
              ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

              ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
              ((eq? selector 'get-sala-saida)
               (lambda ()
                 self-sala-saida))

              ((eq? selector 'set-sala-saida)
               (lambda (nova-sala-saida)
                 (set! self-sala-saida nova-sala-saida)))
              ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

              ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
              ((eq? selector 'get-sala-entrada)
               (lambda()
                 self-sala-entrada))

              ((eq? selector 'set-sala-entrada)
               (lambda (nova-sala-entrada)
                 (set! self-sala-entrada nova-sala-entrada)))
              ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

              ;;;;;;;;;;;;;;;;;;;;;;;;;;
              ((eq? selector 'has-porta?)
               (lambda()
                 self-has-porta?))

              ((eq? selector 'set-has-porta?)
               (lambda(tem-porta?)
                 (set! self-has-porta? tem-porta?)))
              ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                ;;;;;;;;;;;;;;;;;;;;;;;;;;;
              ((eq? selector 'is-trancada?)
               (lambda ()
                 (if self-has-porta?
                     self-trancada?
                     #f)))

              ((eq? selector 'set-trancada?)
               (lambda (estado?)
                 (set! self-trancada? estado?)))
              ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

              ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
              ((eq? selector 'get-chave-que-abre)
               (lambda ()
                 (if self-has-porta?
                     self-chave-que-abre
                     #f)))

              ((eq? selector 'set-chave-que-abre)
               (lambda (nova-chave-que-abre)
                 (if has-porta?
                     (set! self-chave-que-abre nova-chave-que-abre)
                     #f)))
              ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

              (else
               #f))))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; EXEMPLO DE USO:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; (define porta1 (cria-porta "Porta 1"
;;                         "Esta porta dá para a sala 2"
;;                         's2
;;                         's1
;;                         #t
;;                         'chave-2-1))
;; ((porta1 'get-nome))
;; ((porta1 'set-nome) "Novo nome para porta 1")
;; ((porta1 'is-trancada?))
;; ((porta1 'set-trancada?) #f)
;; ((porta1 'get-chave-que-abre))
;; ((porta1 'set-chave-que-abre) 'chave-3-1)
;; ((porta1 'get-sala-saida))
;; ((porta1 'set-sala-saida) 's1)
;; ((porta1 'get-sala-entrada))
;; ((porta1 'set-sala-entrada) 's3)
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
